using Sirenix.OdinInspector;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;

namespace IQIGame.Onigao.GamePlay
{
    public class EffectControlBehaviour : MonoBehaviour
    {
        //[HideInInspector] 
        [SerializeField] public float startDuration;
        [SerializeField] public float loopDuration;
        [SerializeField] public float endDuration;
        [SerializeField] public float allDuration;
        [SerializeField] public bool threePart; // 三段式特效
        public float duration => Mathf.Max(this.allDuration, this.startDuration + this.loopDuration + this.endDuration);

        //[HideInInspector] 
        [SerializeField] public bool loop;
        [SerializeField] public ParticleSystem mainParticle;
        [SerializeField] public PlayableDirector director; // 用来处理额外播放其他timeline

        public void Hide()
        {
            this.gameObject.SetActive(false);
        }

        /// <summary>
        /// 特效控制类型
        /// </summary>
        public enum EffectControlType
        {
            None = 0,
            Laser = 1,
            Bullet = 2,
            OtherDummy = 3,
        }

        /// <summary>
        /// 特效生效阶段
        /// </summary>
        public enum EEffectStageType
        {
            All,
            Start,
            Loop,
            End
        }

        [Serializable]
        public class ParticleControlData
        {
            public EffectControlType controlType;
            public EEffectStageType stageType;

            public ParticleSystem particle;
            public ParticleSystem[] particles;

            public LineRenderer LineRenderer;

            public int[] paramInt;
            public bool onlyRotateY;
        }

        /// <summary>
        /// 特效控制数据
        /// </summary>
        [SerializeField] public List<ParticleControlData> controlData;

        public bool isEnd => this._curPlayStage == EEffectStageType.End &&
                             (this.endDuration <= 0 || this._endPlayTime >= this.endDuration);

        public float curPlayTime;
        private float _startPlayTime;
        private float _endPlayTime;
        private float _loopPlayTime;

        public Vector3 startPos;
        public Vector3 targetPos;
        public Vector3 targetScale;

        public Func<int, Transform> getBindPoint;
        public EVFXSpace dummyFollowType;

        private EEffectStageType _curPlayStage;

        public EEffectStageType curPlayStage
        {
            get => this._curPlayStage;
            set
            {
                this._curPlayStage = value;
                for (int i = 0; i < this.controlData.Count; i++)
                {
                    var rCtrlData = this.controlData[i];
                    if (rCtrlData.particle)
                    {
                        rCtrlData.particle.gameObject.SetActive(rCtrlData.stageType == EffectControlBehaviour.EEffectStageType.All ||
                                                                rCtrlData.stageType == this._curPlayStage);
                    }
                }
            }
        }

        // 内置的timeline是否正在播放
        private bool _subTimelineIsPlaying = false;

        public void Play(Vector3 targetPos, Func<int, Transform> getBindPoint, EEffectStageType startStage)
        {
            this.startPos = this.transform.position;
            this.targetPos = targetPos;
            this.getBindPoint = getBindPoint;

            this.gameObject.SetActive(true);
            // 若开始播放时指定状态,就指定初始时间让继续播
            if (startStage == EEffectStageType.End)
            {
                this.curPlayTime = this.startDuration + this.loopDuration;
            }
            else if (startStage == EEffectStageType.Loop)
            {
                this.curPlayTime = this.startDuration;
            }
            this.ParticleSimulate(this.curPlayTime);
            
            if (!this.threePart)
            {
                if (this.mainParticle)
                {
                    this.mainParticle.Play();
                }
                this.curPlayStage = startStage == EEffectStageType.End ? EEffectStageType.End : EEffectStageType.All;
            }
            else
            {
                this.curPlayStage = EEffectStageType.Start;
            }
        }

        // 直接指定特效生命周期中的时间，主动loop交到外侧控制器处理
        public void OnUpdate(float deltaTime)
        {
            this.curPlayTime += deltaTime;
            switch (this.curPlayStage)
            {
                case EEffectStageType.Start:
                    this._startPlayTime = this.curPlayTime;
                    if (this._startPlayTime >= this.startDuration)
                    {
                        this.curPlayStage = EEffectStageType.Loop;
                    }
                    break;
                case EEffectStageType.Loop:
                    this._loopPlayTime = this.curPlayTime - this.startDuration;
                    if (this.loopDuration > 0 && this._loopPlayTime >= this.loopDuration)
                    {
                        this.curPlayStage = EEffectStageType.End;
                    }
                    break;
                case EEffectStageType.End:
                    this._endPlayTime = this.curPlayTime - this.startDuration - this.loopDuration;
                    break;
            }
            this.OnFrameUpdate();
        }

        private void OnFrameUpdate()
        {
            for (int i = 0; i < this.controlData.Count; i++)
            {
                var rData = this.controlData[i];
                if (rData.stageType != this.curPlayStage && rData.stageType != EffectControlBehaviour.EEffectStageType.All)
                {
                    continue;
                }
                switch (rData.controlType)
                {
                    case EffectControlBehaviour.EffectControlType.Laser:
                        if (rData.particles.Length > 0 && rData.particles[0])
                        {
                            rData.particles[0].transform.position = this.startPos;
                        }
                        if (rData.particles.Length > 1 && rData.particles[1])
                        {
                            rData.particles[1].transform.position = this.targetPos;
                        }
                        if (rData.LineRenderer)
                        {
                            rData.LineRenderer.SetPosition(0, this.startPos);
                            rData.LineRenderer.SetPosition(1, this.targetPos);
                        }
                        break;
                    case EffectControlBehaviour.EffectControlType.Bullet:
                        // 子弹特效的位置由bulletComponent控制
                        if (rData.particle)
                        {
                            rData.particle.transform.localPosition = this.targetPos;
                            if (rData.paramInt.Get(1) == 1)
                            {
                                rData.particle.transform.localScale = this.targetScale;
                            }
                        }
                        break;
                    case EffectControlBehaviour.EffectControlType.OtherDummy:
                        if (rData.particle && this.getBindPoint != null)
                        {
                            var rParticleTrans = rData.particle.transform;
                            var rDummyTrans = this.getBindPoint.Invoke(rData.paramInt.Get(0));
                            if ((this.dummyFollowType & EVFXSpace.WorldPosition) != 0)
                            {
                                rParticleTrans.position = rDummyTrans.position;
                            }
                            if ((this.dummyFollowType & EVFXSpace.WorldRotation) != 0)
                            {
                                rParticleTrans.rotation = rDummyTrans.rotation;
                            }
                        }
                        break;
                }
                // 仅水平旋转
                if (rData.onlyRotateY)
                {
                    Quaternion parentRotation = this.transform.rotation;

                    // 将父节点的旋转限制在XZ轴上
                    Vector3 parentEulerAngles = parentRotation.eulerAngles;
                    parentEulerAngles.x = 0f;
                    parentEulerAngles.z = 0f;

                    // 创建新的旋转
                    Quaternion newRotation = Quaternion.Euler(parentEulerAngles);

                    // 将新的旋转应用于子节点
                    rData.particle.transform.rotation = newRotation;
                }
            }
        }

        public void ParticleSimulate(float curTime)
        {
            this.curPlayTime = curTime;
            if (!this.threePart)
            {
                if (this.mainParticle)
                {
                    if (this.curPlayTime > this.duration)
                    {
                        this.mainParticle.Simulate(0, true, true);
                        return;
                    }
                    this.mainParticle.Simulate(this.curPlayTime, true, true);
                }
                if (this.director && this.director.state != PlayState.Playing && !this._subTimelineIsPlaying)
                {
                    this.director.Play();
                    this._subTimelineIsPlaying = true;
                }
            }
            else
            {
                for (int i = 0; i < this.controlData.Count; i++)
                {
                    var rCtrlData = this.controlData[i];
                    if (rCtrlData.stageType == this.curPlayStage)
                    {
                        float fPlayTime = this.curPlayTime;
                        switch (this.curPlayStage)
                        {
                            case EEffectStageType.Loop:
                            {
                                this._loopPlayTime = this.curPlayTime - this.startDuration;
                                this._loopPlayTime %= this.loopDuration;
                                fPlayTime = this._loopPlayTime;
                                break;
                            }
                            case EEffectStageType.Start:
                            {
                                if (this._startPlayTime > this.startDuration)
                                {
                                    fPlayTime = 0;
                                }
                                else
                                {
                                    fPlayTime = this._startPlayTime;
                                }
                                break;
                            }
                            case EEffectStageType.End:
                            {
                                this._endPlayTime = this.curPlayTime - this.startDuration - this.loopDuration;
                                if (this._endPlayTime > this.endDuration)
                                {
                                    fPlayTime = 0;
                                }
                                else
                                {
                                    fPlayTime = this._endPlayTime;
                                }
                                break;
                            }
                        }
                        if (rCtrlData.particle)
                        {
                            rCtrlData.particle.Simulate(fPlayTime, true, true);
                        }
                    }
                }
            }
        }

        public void RestartLoop()
        {
            this.curPlayTime = this.startDuration;
            if (this.threePart)
            {
                for (int i = 0; i < this.controlData.Count; i++)
                {
                    var rCtrlData = this.controlData[i];
                    switch (rCtrlData.stageType)
                    {
                        case EEffectStageType.Loop:
                            break;
                        case EEffectStageType.All:
                            break;
                    }
                    if ((rCtrlData.stageType == EEffectStageType.Loop || rCtrlData.stageType == EEffectStageType.All) &&
                        rCtrlData.particle && !rCtrlData.particle.main.playOnAwake)
                    {
                        rCtrlData.particle.time = 0;
                        rCtrlData.particle.Simulate(this.curPlayTime);
                        rCtrlData.particle.Play();
                    }
                }
            }
            else
            {
                if (this.mainParticle && !this.mainParticle.main.playOnAwake)
                {
                    this.mainParticle.time = 0;
                    this.mainParticle.Simulate(this.curPlayTime);
                    this.mainParticle.Play();
                }
            }
        }
    }
}